--[[
    游戏服调度机器人接口
--]]

local skynet = require "skynet"
local cluster = require "skynet.cluster"
local filelog = require "filelog"
local base = require "base"
local filename = "dnscheduler.lua"

require "pubenum"

--桌子类型
local ETableType = {
    TABLE_TYPE_DIAMOND = 1, --金豆场
    TABLE_TYPE_FANKA = 2,   --房卡
    TABLE_TYPE_COIN = 3,    --金币
}

local gamename = "dnnode"

local dnscheduler = {
    CMD = {},
    handler = {},
    robot_tableinfo = {},
    alltableinfo = {},   --所有桌子数据
    interval_time = 3,   --调度间隔时间，默认3s
    table_list = {},     --调度桌子列表
    is_run = false,       --是否运行

}

---返回机器人的数量
function dnscheduler.CMD.getrobotnum()

end

function dnscheduler.CMD.change_schedule_state(newstate)
    if dnscheduler.is_run == newstate then
        return
    end

    dnscheduler.is_run = newstate
    if newstate then
        dnscheduler.alltableinfo = {}
        dnscheduler.table_list = {}
    end
end

function dnscheduler.handler.request_entertable(table_type, table_index, robotnum, base_score, enter_score)
    --入场，底注随机3~5倍
    local min = 1 * enter_score 
    local max = 5 * enter_score
    local moneyvalue = base.get_random(min, max)
    local robotconf = {diamond = 0, coin = 0, logicname = "dn"}
    if table_type == ETableType.TABLE_TYPE_DIAMOND then
        robotconf.diamond = moneyvalue
        robotconf.coin = base.get_random(9900, 16000) * 10
    elseif table_type == ETableType.TABLE_TYPE_COIN then
        robotconf.coin = moneyvalue
        robotconf.diamond = base.get_random(500, 5000)
    end
    skynet.call(".schedulemgr", "lua", "request_robot_enter", gamename, table_index, robotnum, robotconf)
end

function dnscheduler.handler.request_entermatch(match_type, match_level, robotnum, base_score, enter_score)
    --入场，底注随机3~5倍
    local min = 1 * enter_score 
    local max = 5 * enter_score
    local moneyvalue = base.get_random(min, max)
    local robotconf = {diamond = 0, coin = 0, logicname = "dn"}
    if match_type == "diamond" then
        robotconf.diamond = moneyvalue
        robotconf.coin = base.get_random(9900, 16000) * 10
    elseif match_type == "coin" then
        robotconf.coin = moneyvalue
        robotconf.diamond = base.get_random(500, 5000)
    end
    skynet.call(".schedulemgr", "lua", "request_robot_match", gamename, match_type, match_level, robotnum, robotconf)
end

function dnscheduler.handler.request_leavetable(table_index, rids)
    skynet.call(".schedulemgr", "lua", "request_robot_leave", gamename, table_index, rids)
end

function dnscheduler.CMD.robotentermatchtable(match_type, match_level, robotnum, enter_score)
    --入场，底注随机3~5倍
    local min = 1 * enter_score 
    local max = 5 * enter_score
    local moneyvalue = base.get_random(5000, 10000)
    local robotconf = {diamond = 0, coin = 0, logicname = "dn"}
    if match_type == "diamond" then
        robotconf.diamond = moneyvalue
    elseif match_type == "coin" then
        robotconf.coin = moneyvalue
    end
    skynet.call(".schedulemgr", "lua", "request_robot_match", gamename, match_type, match_level, robotnum, robotconf)
end

function dnscheduler.CMD.robotcreatepublictable(table_conf)
    local status, result = skynet.pcall(cluster.call, gamename, ".router", "robotcreatepublictable", table_conf)
    if not status then return nil end
    return result
end


function dnscheduler.handler.request_createtable(base_score)
    --创建自建桌 底注范围(50-100金豆) 人数条件(非满人桌不足2桌)
    local table_conf = {
        is_public           = 1,    --        // 是否允许陌生人加入
        table_mode          = 1,    --        // 牌型倍率选择(1 普通模式 2 扫雷模式)
        play_game_type      = base.get_random(1,2),    --        // 玩法选择(1 自由抢庄 2 看牌抢庄)
        xia_zhu_type        = 1,    --        // 下注倍数(1 小倍, 2 中倍 3 大倍)
        score_diamond       = 0,    --    // 底注
        enter_diamond       = 0,    --    //进桌多少钻石
        leave_diamond       = 0,    --    //离桌多少钻石
        table_type          = 1,    --    // 创建房间类型(2 自建房卡桌 1 自建钻石桌)
        is_open_flush       = 2,       --        // 是否开启 同花顺牛,葫芦牛,同花牛,顺子牛 1 不开启 2 开启
        max_player_num      = 7,    --   // 设置玩家人数(默认5人,可选择5人,7人)
        --//只有房卡场 
        retain_to_num       = 10,   --       //创建房间局数，只创建房卡需要
        cost_type           = 1,    --       //房卡花费模式：1 房主自付，2 AA
        match_type          = 0,
    }
    table_conf.score_diamond = base_score or 50               --50或100局数
    table_conf.enter_diamond = 30 * table_conf.score_diamond
    table_conf.leave_diamond = 30 * table_conf.score_diamond
    --建桌并进桌
    local status, result = skynet.pcall(cluster.call, gamename, ".router", "robotcreatepublictable", table_conf)
    if status and result and result.retcode == nil then
        dnscheduler.handler.request_entertable(table_conf.table_type, result.table_index, 1, table_conf.score_diamond, table_conf.enter_diamond)
    end
end
--[Comment]
-- 运行进桌调度器
--
function dnscheduler.handler.run_enter_scheduler()
    while true do
        skynet.sleep((dnscheduler.interval_time + 2 ) * 100)
        if dnscheduler.is_run then
            skynet.pcall(dnscheduler.handler.do_enter_schedule)
        end
    end
end

--[Comment]
-- 运行离桌调度器
--
function dnscheduler.handler.run_leave_scheduler()
    while true do
        skynet.sleep(dnscheduler.interval_time * 100)
        if dnscheduler.is_run then
            skynet.pcall(dnscheduler.handler.do_leave_schedule)
        end
    end
end

---------------------------

--[Comment]
-- 初始化
--
function dnscheduler.CMD.init(conf)
    conf = conf or {}
    dnscheduler.interval_time = conf.interval_time or 3
end

function dnscheduler.handler.get_alltableinfo()
    local status,result = skynet.pcall(cluster.call, gamename, ".router", "get_alltableinfo")
    if status and result then
        dnscheduler.alltableinfo = result
    else
        dnscheduler.alltableinfo = {}
    end
end

function dnscheduler.handler.do_enter_schedule()
    -- body
    --拉桌子数据
    dnscheduler.handler.get_alltableinfo()

    --桌子数量
    local ptable_nums = {[50] = 0, [100] = 0}

    --匹配桌数量
    local mtable_nums = {}

    --最大匹配桌数量
    local mtable_maxs = {[50] = 1, [100] = 0}

    --根据时间设置匹配桌数目
    local tm = os.date("*t")
    local cur_hour = tonumber(tm.hour)
    if cur_hour >= 0 and cur_hour < 4 then          --0点-4点，拥挤
        mtable_maxs = {[10] = 1, [50] = 2, [100] = 1}
    elseif cur_hour >= 4 and cur_hour < 9 then      --4点-9点，流畅
        mtable_maxs = {[10] = 1, [50] = 1, [100] = 0}
    elseif cur_hour >= 9 and cur_hour < 12 then     --9点-12点，拥挤
        mtable_maxs = {[10] = 1, [50] = 2, [100] = 1}
    elseif cur_hour >= 12 and cur_hour < 16 then    --12~16点，火爆
        mtable_maxs = {[10] = 1, [50] = 3, [100] = 2}
    elseif cur_hour >= 16 and cur_hour < 19 then    --16~19点，拥挤
        mtable_maxs = {[10] = 1, [50] = 2, [100] = 1}
    elseif cur_hour >= 19 and cur_hour < 24 then    --19~24点，火爆
        mtable_maxs = {[10] = 1, [50] = 3, [100] = 2}
    end

    -----------------------
    ---进桌调度

    --处理缺人桌子,只处理1桌50和1桌100的桌子
    local tableinfos = dnscheduler.alltableinfo.tableinfos or {}
    for _,tableinfo in pairs(tableinfos) do
        if tableinfo.table_type == 1 then
            local base_score = tableinfo.base_score or 0
            if tableinfo.is_public == 1 and ptable_nums[base_score] == 0 then    --只处理公开桌
                local table_index = tableinfo.table_index
                if tableinfo.cur_player > 0 and tableinfo.cur_player < 3  then   --小于3人，概率加入机器人
                    local min = 50
                    local robot_num = #(tableinfo.robot_rids)
                    local player_num = tableinfo.cur_player
                    if player_num == 1 and robot_num == 0 then          --1个真人
                        min = 80
                    elseif player_num == 1 and robot_num == 1 then      --1个机器人
                        min = 50
                    elseif player_num == 2 and robot_num == 0 then      --2个真人
                        min = 30
                    elseif player_num == 2 and robot_num == 1 then      --1个真人，1个机器人
                        min = 25
                    elseif player_num == 2 and robot_num == 2 then      --2个机器人
                        min = 20
                    end
                    local r = base.get_random(1,100)
                    if r <= min then
                        dnscheduler.handler.request_entertable(tableinfo.table_type, table_index, 1, tableinfo.base_score, tableinfo.enter_score)
                    end
               end
               ptable_nums[base_score] = 1
            end
            --统计50底注匹配桌数量
            local match_type = tableinfo.match_type or 0
            if match_type > 0 and tableinfo.cur_player > 0 then
                mtable_nums[match_type] = (mtable_nums[match_type] or 0) + 1
            end
        end
    end

    --处理金豆匹配场
    local match_infos = dnscheduler.alltableinfo.match_infos or {}
    for level,info in pairs(match_infos) do
        local mod = info.wait_num % info.max_player
        --匹配玩家少于2人，概率加入机器人
        local mtable_num = mtable_nums[level] or 0
        local mtable_max = mtable_maxs[info.base_score] or 0
        if mod == 1 or mtable_num < mtable_max then
            local r = base.get_random(1,2)
            if r == 1 then
                dnscheduler.handler.request_entermatch("diamond", level, 1, info.base_score, info.enter_score)
            end
        end
    end
    
    --处理金币匹配场
    local coinmatch_infos = {}
    for level,info in pairs(coinmatch_infos) do
        if info.wait_num % info.max_player ~= 0 then
            local r = base.get_random(1,2)
            if r == 1 then
                ---dnscheduler.handler.request_entermatch("coin", level, 1, info.base_score, info.enter_score)
            end
        end
    end

    ----------------
    ---建桌调度

    --保证1个50底注桌，1个100底注桌
    for score,num in pairs(ptable_nums) do
        if num == 0 then
            dnscheduler.handler.request_createtable(score)
        end
    end

    return true
end

function dnscheduler.handler.do_leave_schedule()
    -- body
    --拉桌子数据
    dnscheduler.handler.get_alltableinfo()

    ----------------
    ---离桌调度

    --处理满人桌子
    local tableinfos = dnscheduler.alltableinfo.tableinfos or {}
    for _,tableinfo in pairs(tableinfos) do
        local match_type = tableinfo.match_type or 0
        if tableinfo.table_type == 1 then
            if tableinfo.is_public == 1 or match_type > 0 then    --只处理公开桌或匹配场
                if not tableinfo.is_ingame then
                    ---filelog.sys_error("-----tableinfo.robot_rids-----", tableinfo.robot_rids)
                    local robot_num = #(tableinfo.robot_rids)
                    local table_index = tableinfo.table_index
                    if robot_num == tableinfo.cur_player and robot_num >= 8 then --超过3个机器人，随机离桌1~3个
                        --1/3概率全离桌,2/3概率部分离桌
                        local rids = {}
                        if base.get_random(1,3) == 1 then
                            for index, value in ipairs(tableinfo.robot_rids) do
                                if value.game_num > 0 and value.total_score > 0 then table.insert(rids, value.rid) end 
                            end
                        else
                            local max = robot_num
                            local n = base.get_random(1,3)
                            for i = 1,n do
                                local idx = base.get_random(1,max)
                                local ridobj = tableinfo.robot_rids[idx]
                                if ridobj.game_num > 0 and ridobj.total_score > 0 then 
                                    table.insert(rids, ridobj.rid) 
                                    tableinfo.robot_rids[idx] = tableinfo.robot_rids[max]
                                    max = max - 1
                                end
                            end
                        end
                        dnscheduler.handler.request_leavetable(table_index, rids)
                    elseif not tableinfo.is_ingame then           --检测机器人是否可以离桌，每次只离桌一个
                        local num = #(tableinfo.robot_rids)
                        if num > 0 then
                            local status = nil
                            local idx = base.get_random(1,num)
                            for i = idx,idx do
                                local ridobj = tableinfo.robot_rids[i]
                                if ridobj.game_num > 0 and ridobj.total_score > 0 then
                                    status = skynet.call(".robotmgr", "lua", "check_leavetable", ridobj.rid)
                                    if status then
                                        break
                                    end
                                end
                                i = i % num + 1
                            end
                            --机器人超过2人，2/3概率离桌1人
                            if not status and num > 4 then
                                if base.get_random(1,3) == 1 then
                                    local k = base.get_random(1,num)
                                    local ridobj = tableinfo.robot_rids[k]
                                    if ridobj.game_num > 0 and ridobj.total_score > 0 then
                                        dnscheduler.handler.request_leavetable(table_index, {ridobj.rid})
                                    end
                                end 
                            end
                        end 
                    end
                end
            end
        end
    end
end


function dnscheduler.monitor()
    skynet.fork(dnscheduler.handler.run_enter_scheduler)
    skynet.fork(dnscheduler.handler.run_leave_scheduler)
end

skynet.start(function()
    skynet.dispatch("lua",function(session, source, cmd, ...)
        local f = dnscheduler.CMD[cmd]
        if f then
            skynet.retpack(f(...))
        else
            skynet.retpack()
        end
    end)
    dnscheduler.monitor()
end)
